package com.etlmaster.executor.utils;

import java.io.InputStreamReader;
import java.io.BufferedReader;
import java.io.IOException;
import java.lang.reflect.Field;



/**
 * @author Larry
 * @copyright Larry@etlMaster
 * @since 2017-09-10
 */
public class ProcessHelper {
	
	
	public static int executor(ProcessCallback callback, String... command) throws IOException{
		try {
			ProcessBuilder processBuilder = new ProcessBuilder();
			processBuilder.redirectErrorStream(true);
			
			processBuilder.command(command);
			Process process = processBuilder.start();
	
			callback.setProcessId(getProcessId(process));
			
			ProcessorPrintThread thread1 = new ProcessorPrintThread(callback, new BufferedReader(new InputStreamReader(process.getInputStream(), "utf-8")));
			new Thread(thread1).start();
			
			/*ProcessorPrintThread thread2 = new ProcessorPrintThread(callback, new BufferedReader(new InputStreamReader(process.getErrorStream(), "utf-8")));
			new Thread(thread2).start();*/
		
			int retrunCode = process.waitFor();
			if (retrunCode == 0) {
				process.destroy();
			}
			return retrunCode;
		} catch (InterruptedException e) {
			e.printStackTrace();
			LogWriter.addLog("ERROR","进程处理失败{}",e.getMessage());
			return -1;
		}finally{
			callback.finish();
		}
	}
	
	public static String getProcessId(Process process) {
		String pid = "-1";
		try {
			if (System.getProperty("os.name").toLowerCase().startsWith("win")) {
				if (process.getClass().getName().equals("java.lang.Win32Process")
						|| process.getClass().getName()
								.equals("java.lang.ProcessImpl")) {
					Field f = process.getClass().getDeclaredField("handle");
					f.setAccessible(true);
					pid = f.get(process).toString();
				}
			} else {
				if (process.getClass().getName()
						.equals("java.lang.UNIXProcess")) {
					Field f = process.getClass().getDeclaredField("pid");
					f.setAccessible(true);
					pid = String.valueOf(f.getInt(process));
				}
			}
		} catch (Exception ex) {
		}
		return pid;
	}
}

class ProcessorPrintThread implements Runnable {

	ProcessCallback callback;
	BufferedReader br;

	public ProcessorPrintThread(ProcessCallback callback, BufferedReader br) {
		super();
		this.callback = callback;
		this.br = br;
	}

	@Override
	public void run() {
		String line = null;
		try {
			while ((line = br.readLine()) != null) {
				callback.handle(line);
			}
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
	
	
}
